/**
 * @file voice_msg.h
 *
 */
#ifndef VOICE_MSG_H
#define VOICE_MSG_H

#ifdef __cplusplus
extern "C" {
#endif

/*********************
*      INCLUDES
*********************/

#ifdef LV_CONF_INCLUDE_SIMPLE
#include "lvgl.h"
#include "lv_watch_conf.h"
#else
#include "../../../lvgl/lvgl.h"
#include "../../../lv_watch_conf.h"
#endif

#if USE_LV_WATCH_VOICE_MSG != 0

/*********************
*      DEFINES
*********************/
#define VOICE_MSG_TEST 1
#define VOICE_MSG_APP_SPECIFIC_TEST 0 /*for test with VOICE_MSG_TEST set to 1,
                                       *the contacts of phonebook will be modified when voice msg app is opened for the first time.
                                       *please set "number = NULL;" in watch_modem_call_response_clip to enable to receive mt call*/
#define VOICE_MSG_SLIDE_UP_TO_CANCEL_RECORDING 1
#define VOICE_MSG_ENABLE_ONE_UNREAD_MSG 0
#define VOICE_MSG_SORT_CONTACTS_BY_MSG_TIME 0 /*move the contact who receives a new message to the top of contacts list*/

#define VOICE_MSG_AMR_HEAD_SIZE 6
#define VOICE_MSG_EXPRESSION_WIDTH 120
#define VOICE_MSG_EXPRESSION_HEIGHT 120
#define VOICE_MSG_PHOTO_WIDTH 120
#define VOICE_MSG_PHOTO_HEIGHT 120

#define VOICE_MSG_CHAT_TIME_INTERVAL (3 * 60) /*display the time of current chat msg if more than 3 mins from the previous chat msgs*/

/*bit for free num(0 - 31 bit) in lv_obj_t: voice msg index(23 - 31), unread flag(5), direction(4), msg type(0 - 3)*/
#define VOICE_MSG_SET_VOICE_INDEX(free_num, index) (free_num += index << 24)   /*index: 8 bits*/
#define VOICE_MSG_GET_VOICE_INDEX(free_num)        ((uint8_t)(free_num >> 24)) /*index: 8 bits*/
#define VOICE_MSG_SET_UNREAD_FLAG(free_num)        (free_num |= (1 << 5))
#define VOICE_MSG_IS_UNREAD_FLAG(free_num)         ((free_num & (1 << 5)) ? true : false)
#define VOICE_MSG_CLEAR_UNREAD_FLAG(free_num)      (free_num &= ~(1 << 5))
#define VOICE_MSG_SET_MSG_FROM_SERVICE(free_num)   (free_num |= (1 << 4))
#define VOICE_MSG_IS_MSG_FROM_SERVICE(free_num)    ((free_num & (1 << 4)) ? true : false)
#define VOICE_MSG_SET_MSG_TYPE(free_num, msg_type) (free_num += msg_type)      /*voice_msg_type_t: 4 bits*/
#define VOICE_MSG_GET_MSG_TYPE(free_num)           ((uint8_t)(free_num & 0xF)) /*voice_msg_type_t: 4 bits*/

/**********************
*      TYPEDEFS
**********************/
/*the number of group is less than or equal to NV_WATCH_MAX_VOICE_MSG_GROUP_NUM*/
enum {
    VOICE_MSG_FAMILY_GROUP = NV_WATCH_MAX_CONTACT_NUM,
    VOICE_MSG_FRIENDS_GROUP
}; /*index in nv_watch_voice_msg_t*/

enum {
    VOICE_MSG_PORTRAIT_ID_FAMILY_GROUP = WATCH_PORTRAIT_ID_OTHERS + 1,
    VOICE_MSG_PORTRAIT_ID_FRIENDS_GROUP
}; /*portrait id for family group or friends group*/

enum {
    VOICE_MSG_FROM_SELF = 0,
    VOICE_MSG_FROM_ALBUM,
    VOICE_MSG_FROM_IMGVIEWER,
};
typedef uint8_t voice_msg_from_app_t;

typedef struct
{
    char name[NV_CONTACTS_MAX_NAME_LEN];
    char number[NV_CONTACTS_MAX_NUMBER_LEN];
    uint8_t index; /*index in phonebook nvm*/
    uint8_t portrait_id;
    uint8_t mark;
} voice_msg_contact_t;

typedef struct
{
    lv_watch_obj_ext_t old_ext;
    lv_obj_t * page;
    lv_coord_t img_height;
    bool pressing;
    voice_msg_from_app_t other_app; /*ui created by other app*/
    lv_style_t style_cont_mark;
    lv_style_t style_label_mark;
    lv_ll_t * contact_list; /*voice_msg_contact_t*/
    lv_signal_cb_t ancient_page_scrl_signal;
} lv_voice_msg_ext_t;

typedef struct
{
    lv_watch_obj_ext_t old_ext;
    lv_obj_t * label;
} lv_voice_msg_speak_ext_t;

typedef struct
{
    lv_watch_obj_ext_t old_ext;
    lv_ll_t * contact_list; /*voice_msg_contact_t*/
    voice_msg_contact_t * cur_contact;
#if VOICE_MSG_ENABLE_ONE_UNREAD_MSG != 0
    bool voice_playing;
    lv_img_dsc_t * img_src;
    uint8_t index;
    char * name;
    lv_obj_t * img_voice_anim;
    void * voice_data;
    uint32_t voice_size;
#endif
    bool update; /*update in ACT_ID_VOICE_MSG_INCOMING during call or alarm*/
} lv_voice_msg_incoming_ext_t;

typedef struct
{
    lv_watch_obj_ext_t old_ext;
    bool pressing;
    lv_signal_cb_t ancient_page_scrl_signal;
} lv_voice_msg_expression_ext_t;

typedef struct
{
    uint16_t year;
    uint8_t month;
    uint8_t day;
    uint8_t hour;
    uint8_t min;
} voice_msg_time_t;

typedef struct
{
    lv_watch_obj_ext_t old_ext;
    lv_obj_t * list;
    lv_obj_t * cont_title;
    lv_obj_t * label_no_msg;
    lv_obj_t * img_emo;
    lv_obj_t * img_touch;
    hal_rtc_t last_msg_time; /*time of last message*/
    uint8_t msg_count;
    lv_ll_t * contact_list;   /*voice_msg_contact_t*/
    voice_msg_contact_t * cur_contact;
    bool contact_list_update; /*update voice msg interface when to leave voice msg chat interface*/
    uint8_t * buffer;
    MCI_EVNET_T event;
} lv_voice_msg_chat_ext_t;

typedef struct {
    lv_page_ext_t old_ext;
    lv_anim_t voice_playing_anim;
    bool pressing;
    lv_style_t style_cont;
    lv_style_t style_label_time;
    lv_style_t style_text;
    lv_style_t style_label_len_other;
    lv_style_t style_label_len_ui;
} lv_voice_msg_list_ext_t;

enum
{
    VOICE_MSG_TYPE_TIME = 0,
    VOICE_MSG_TYPE_NAME,
    VOICE_MSG_TYPE_TEXT,
    VOICE_MSG_TYPE_VOICE,
    VOICE_MSG_TYPE_EXPRESSION,
    VOICE_MSG_TYPE_PHOTO,
    VOICE_MSG_TYPE_EMO_AND_TOUCH,
    VOICE_MSG_TYPE_UNREAD_FLAG
};
typedef uint8_t voice_msg_type_t;

typedef struct
{
    voice_msg_type_t type;
    char * time_str;
    char * name_str;
    void * data;                 /*file path string if size is 0, otherwise data buffer*/
    uint32_t size;
    uint8_t voice_index;         /*for voice msg*/
    uint8_t have_read;           /*for voice msg: 1 -- read; 0-- unread*/
    uint8_t direction;           /*1-- from other; 0--from self*/
} voice_msg_desc_t;

enum
{
    VOICE_MSG_UPDATE_TYPE_ADD = 0, /*add admin and family group if admin added*/
    VOICE_MSG_UPDATE_TYPE_UPDATE,  /*clear all of messages if number changed*/
    VOICE_MSG_UPDATE_TYPE_DELETE,  /*clear all of messages for all of contacts if admin deleted*/
};
typedef uint8_t voice_msg_update_type_t;

typedef struct
{
    voice_msg_update_type_t type;
    uint8_t index;       /*index if contact added or updated, old index if contact deleted, 0 means admin*/
    char * old_name;     /*valid if name updated or deteled*/
    char * new_name;     /*valid if admin added or name updated*/
    char * number;       /*valid if number changed*/
    uint8_t portrait_id; /*valid if admin added or name changed*/
    uint8_t contact_type;/*0: admin, 1:standby admin, 2:others*/
    uint8_t standby_admin_count;
    uint8_t others_count;
} voice_msg_update_contact_t;

/**********************
* GLOBAL PROTOTYPES
**********************/

/**
 * Create a voice message application
 */
lv_obj_t * voice_msg_create(lv_obj_t * activity_obj, voice_msg_from_app_t other_app, lv_ll_t * contact_list);
void voice_msg_create_event_cb(lv_obj_t * btn, lv_event_t e);
void voice_msg_update_contact_from_phonebook_ind(voice_msg_update_contact_t * update);
void voice_msg_send_emo_event_cb(lv_obj_t * img, lv_event_t e);
void voice_msg_touch_spk_event_cb(lv_obj_t * img, lv_event_t e);
void voice_msg_mt_call_ind(void);
#if 0
void voice_msg_call_end(void);
void voice_msg_alarm_end(void);
void voice_msg_speech_recog_end(void);
void voice_msg_alarm_ind(void);
#endif
void voice_msg_audio_ctrl_callback(AUDIO_CTRL_PRIORITY priority);
void voice_msg_shut_down(void);
void * voice_msg_get_ext(lv_watch_Activity_Id_t actId);
uint32_t voice_msg_read_file_size(char * file_name);
void * voice_msg_read_file_data(char * file_name, uint8_t msg_type, uint32_t * data_size);
void voice_msg_fill_chat_id(app_adaptor_voice_msg_chat_id_t * id, voice_msg_contact_t * contact);
void voice_msg_send_photo(void * buf, uint32_t size, voice_msg_contact_t * contact);
void voice_msg_enlarge_photo(void * small_photo);
void app_adaptor_voice_msg_handle_rcv_ind(app_adaptor_voice_msg_t * msg);
void app_adaptor_voice_msg_handle_send_cnf(watch_app_adp_voice_msg_result_t result);
void voice_msg_set_user_num(lv_obj_t * obj, uint32_t user_num);
void voice_msg_set_user_ptr(lv_obj_t * obj, void * user_ptr);
uint32_t voice_msg_get_user_num(lv_obj_t * obj);
void * voice_msg_get_user_ptr(lv_obj_t * obj);
void voice_msg_play_end(uint32_t len);
void Voice_Msg_Play_Onetime(void * buffer, uint32_t len, HAL_SPEAKER_GAIN volume, CB_FUNC func,
                            void * para);

/**
* Add msg to the voice msg list
*/
lv_obj_t * voice_msg_list_add(lv_obj_t * list, voice_msg_desc_t * msg_desc);
lv_obj_t * voice_msg_list_create(lv_obj_t *par, uint16_t width, uint16_t height);

#if VOICE_MSG_TEST != 0
void voice_msg_test_init(void);
#if VOICE_MSG_APP_SPECIFIC_TEST == 0
void voice_msg_test_clear(void);
void voice_msg_test_clear_nvm(void);
#endif
#ifdef BUILD_IN_PC_SIMULATOR /*for pc test*/
void voice_msg_test_record_buffer_start_req(uint8_t * buffer, uint32_t bufsize, uint32_t maxDurationMs, AUDIO_RECORD_CB_FUNC func);
uint32_t voice_msg_test_record_buffer_stop_req(uint32_t * recSize, uint32_t * durationMs);
void voice_msg_test_file_play_end(void);
void voice_msg_test_tone_play_end(void);
void voice_msg_test_file_play_onetime(const char *path, HAL_SPEAKER_GAIN volume, CB_FUNC func, void *para);
void voice_msg_test_tone_play_onetime(uint32_t *buffer, uint32_t len, HAL_SPEAKER_GAIN volume, CB_FUNC func,
                                      void *para);
#endif
#endif

/*extern phone api*/
bool phone_is_monitor_on(void);

/**********************
*      MACROS
**********************/

#endif /*USE_LV_WATCH_VOICE_MSG*/

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /*VOICE_MSG_H*/
